/*
 * GTestTest - Example of GTest.
 *
 * This file is released to public domain.
 */

#ifndef GAMEWELL_H_
#define GAMEWELL_H_

#include <stdexcept>
#include <vector>

/**
 * Concrete class for the well which contains all the tetrimino pieces.
 *
 * - Rows start at 0 and go from the bottom-up, unlike how most standard
 *   C++ arrays are represented (top-down).
 * - Columns are standard left-right.
 * - Each piece is represented as an int, although this will change later.
 */
class GameWell
{
public:
	/**
	 * The primary constructor.
	 * @param height  The complete number of rows, including hidden rows.
	 * Must be positive, or an exception will be thrown.
	 * @param width  The complete number of columns.
	 * Must not be positive, or an exception will be thrown.
	 * @param hiddenHeight The number of rows on top not to be displayed.
	 * Must not be negative or greater than height, or an exception will be
	 * thrown.
	 */
	GameWell(int totalHeight, int width, int hiddenHeight);

	/// @returns a positive number that is the horizontal dimension.
	int width();

	/// @returns a positive number that is the complete vertical dimension.
	int height();

	/// @returns a positive number that is only the height that can be seen.
	int visibleHeight();

	/**
	 * Get the piece of a tetrimino at a certain location of the well.
	 * @param row  the vertical position to grab the piece. 0 is at the bottom.
	 * An exception will be thrown if the position is less than 0 or greater
	 * than height.
	 * @param col  the horizonal position to grab the piece. 0 is at the left.
	 * An exception will be thrown if the position is less than 0 or greater
	 * than width.
	 *
	 * @returns 0 for unoccupied space, or any other integer if it is occupied.
	 */
	int piece(int row, int col);

private:
	const int mHeight;
	const int mWidth;
	const int mHiddenHeight;
	std::vector<std::vector<int> > mPieces;
};

GameWell::GameWell(int height, int width, int hiddenHeight) :
	mHeight(height), mWidth(width), mHiddenHeight(hiddenHeight)
{
	if (mHeight < 1)
	{
		throw std::invalid_argument("height must be positive.");
	}
	if (mWidth < 1)
	{
		throw std::invalid_argument("width must be positive.");
	}
	if (mHiddenHeight < 1 || mHiddenHeight > mHeight)
	{
		throw std::invalid_argument(
				"hiddenHeight must be positive and less than height.");
	}

	// Everything is safe, now create the appropriate-sized empty well.
	mPieces = std::vector<std::vector<int> >(height);

	for (int row = 0; row < height; ++row)
	{
		mPieces[row] = std::vector<int>(width);

		for (int col = 0; col < width; ++col)
		{
			mPieces[row][col] = 0;
		}
	}
}

int GameWell::width()
{
	return mWidth;
}

int GameWell::height()
{
	return mHeight;
}

int GameWell::visibleHeight()
{
	return mHeight - mHiddenHeight;
}

int GameWell::piece(int row, int col)
{
	return mPieces[row][col];
}

#endif /* GAMEWELL_H_ */
